﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Microsoft.Samples.Kinect.SkeletonBasics
{
    class GestureRecognition
    {

        private List<Gesture> gestures = new List<Gesture>();
        private List<Gesture[]> gestureOverrides = new List<Gesture[]>();
        private List<float[]> data = new List<float[]>();
        private int maxLength = 0;
        private String gestureInfo = "";

        public GestureRecognition() {

            Gesture shootGest = new Gesture("shoot", "shootPC.csv", "shootColumnMeans.csv", "shootModel.csv", "shootCovs.csv", 55, 60, "All", 5, 10f);
            Gesture dribRightGest = new Gesture("dribbleRight", "dribblePC.csv", "dribbleColumnMeans.csv", "dribbleModel.csv", "dribbleCovs.csv", 20, 25, "Right Arm", 10, 8f);
            Gesture passGest = new Gesture("pass", "passPC.csv", "passColumnMeans.csv", "passModel.csv", "passCovs.csv", 35, 45, "All", 5f, 4f);
            Gesture setShootGest = new Gesture("setShoot", "shootPC.csv", "shootColumnMeans.csv", "shootModel.csv", "shootCovs.csv", 30, 40, "All", 10, 10f);
            Gesture setPassGest = new Gesture("setPass", "passPC.csv", "passColumnMeans.csv", "passModel.csv", "passCovs.csv", 30, 35, "All", 10f, 4f);
            Gesture setRightPassGest = new Gesture("setPass", "rightPassPC.csv", "rightPassColumnMeans.csv", "rightPassModel.csv", "rightPassCovs.csv", 30, 35, "All", 10f, 4f);
            Gesture rightPassGest = new Gesture("rpass", "rightPassPC.csv", "rightPassColumnMeans.csv", "rightPassModel.csv", "rightPassCovs.csv", 35, 45, "All", 5f, 4f);

            gestures.Add(shootGest);
            gestures.Add(dribRightGest);
            gestures.Add(passGest);
            gestures.Add(setShootGest);
            gestures.Add(setPassGest);
       //     gestures.Add(rightPassGest);
            gestures.Add(setRightPassGest);

            this.setGestureOverride(passGest, setPassGest);
            this.setGestureOverride(passGest, setShootGest);
            this.setGestureOverride(passGest, setRightPassGest);

            this.setGestureOverride(rightPassGest, setPassGest);
            this.setGestureOverride(rightPassGest, setRightPassGest);
            this.setGestureOverride(rightPassGest, setShootGest);

            this.setGestureOverride(dribRightGest, setPassGest);
            this.setGestureOverride(dribRightGest, passGest);
            this.setGestureOverride(dribRightGest, shootGest);



            foreach (Gesture g in gestures) {
                if (g.getModelLength() > maxLength) {
                    maxLength = g.getModelLength();
                }
            }
        }

        public void doCheck() {

            gestureInfo = "";
            float aveError = 100000;
            double DTWValue = 100000;
            List<Gesture> candidates = new List<Gesture>();


            foreach (Gesture gest in gestures) {

                if (gest.getModelLength() <= data.Count)
                {

                    if (gest.getDistFromModelPoint(gest.getStartThreshold(), data) < gest.getGMRThreshold())
                    {
                 //       Console.WriteLine(gest.getName() + " dist " + gest.getDistFromModelPoint(gest.getStartThreshold(), data) + " " + gest.getGMRThreshold());
                        candidates.Add(gest);
                    }
                }
            }

            foreach (Gesture gest in candidates){

                bool isOverriden = false;

                foreach (Gesture[] a in gestureOverrides){

                    if (a[0].Equals(gest)) {
                        foreach (Gesture b in candidates) {
                            if (a[1].Equals(b)) {
                                isOverriden = true;
                            }
                        }
                    }
                }

                if (!isOverriden && gest.checkForDTWDistance(data) && gest.getDTWValue() < DTWValue)
                {
                    gestureInfo = gest.getName();
                    //    aveError = gest.getAverageError();
                    DTWValue = gest.getDTWValue();
                    //    if(!gestureInfo.StartsWith("p"))
                }
            
            }

            if (!gestureInfo.Contains("set") && !gestureInfo.Equals(""))
            {
                Console.WriteLine("best is " + gestureInfo + " " + DTWValue);
                Console.WriteLine();
                Server.setGestureString(gestureInfo);

            }
            else {
                gestureInfo = "";
            }

            //          Console.WriteLine(gest.getName() + "SSS");

        }

        public void receiveRawData(float[] d){

            if (data.Count >= maxLength) {
                data.RemoveAt(0);
            }

            data.Add((float[])d.Clone());

            this.doCheck();
        }

        public String getGestureInfo() {
            return gestureInfo;
        }

        public int getGesturesRecognized() {
            return gestures.Count;
        }

        public void clearGestures() {

            gestureInfo = "";
        }

        private void setGestureOverride(Gesture mainGesture, Gesture g){

                Gesture[] a = new Gesture[2]{mainGesture, g};
                gestureOverrides.Add(a);
                    
        }

    }
}
